package com.mytrip.aop;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Enumeration;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.newheight.dao.TimeTaskDao;
import com.newheight.model.BackOperator;
import com.newheight.model.TimeTask;
import com.newheight.model.TimeTaskStatus;
import com.newheight.util.Constant;

@Aspect
public class TimeTaskAspect extends BaseAspect {
	private TimeTaskDao timeTaskDao;
	// ~ method ==================================================================
	
	@Pointcut("execution(* org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean.getObject())")
	public void jobPt() {
	}

	@Around("jobPt() && target(t)")
	public Object jobAdvice(ProceedingJoinPoint pjp, MethodInvokingJobDetailFactoryBean t) throws Throwable {
		Object proceed = pjp.proceed();
		JobDetail jd=(JobDetail)proceed;
		jd.setJobClass(ProxyJob.class);
		jd.getJobDataMap().put("timeTaskDao", timeTaskDao);
		TimeTaskStatus tts = new TimeTaskStatus();
		jd.getJobDataMap().put("timeTaskStatus", tts);
		return proceed;
	}
	@Pointcut("execution(* org.springframework.scheduling.quartz.SchedulerFactoryBean.getObject())")
	public void schedulerPt() {
	}
	
	@Around("schedulerPt() && target(t)")
	public Object schedulerAdvice(ProceedingJoinPoint pjp, SchedulerFactoryBean t) throws Throwable {
		Object proceed = pjp.proceed();
		Scheduler sch=(Scheduler)proceed;
		Constant.schedulerSet.add(sch);
		return proceed;
	}
	public static class ProxyJob extends MethodInvokingJobDetailFactoryBean.MethodInvokingJob {
		private final Log log = LogFactory.getLog(ProxyJob.class);
		private TimeTaskDao timeTaskDao;
		private TimeTaskStatus timeTaskStatus;
		private BackOperator backOperator;
		public TimeTaskStatus getTimeTaskStatus() {
			return timeTaskStatus;
		}
		public void setTimeTaskStatus(TimeTaskStatus timeTaskStatus) {
			this.timeTaskStatus = timeTaskStatus;
		}
		public BackOperator getBackOperator() {
			return backOperator;
		}
		public void setBackOperator(BackOperator backOperator) {
			this.backOperator = backOperator;
		}
		public TimeTaskDao getTimeTaskDao() {
			return timeTaskDao;
		}
		public void setTimeTaskDao(TimeTaskDao timeTaskDao) {
			this.timeTaskDao = timeTaskDao;
		}
		public void executeInternal(JobExecutionContext context) throws JobExecutionException {
			TimeTask tt = new TimeTask();
			tt.setName(context.getJobDetail().getName());
			tt.setStartTime(new Date());
			InetAddress ip = getIp();
			if(ip!=null) {
				tt.setIp(ip.getHostAddress());
				tt.setHostName(ip.getHostName());
			}
			JobExecutionException je=null;
			if(!timeTaskStatus.isDisabled()) {
				try {
					super.executeInternal(context);
					tt.setResult(TimeTask.SUCCESS);
				} catch (Exception e) {
					tt.setResult(TimeTask.FAIL);
					log.error("::",e);
					if (e instanceof JobExecutionException) {
						je=(JobExecutionException) e;
					}
				}
			} else {
				tt.setResult(TimeTask.SKIP);
			}
			tt.setBackOperator(backOperator);
			tt.setEndTime(new Date());
			timeTaskDao.save(tt);
			if(je!=null) {
				throw je;
			}
		}
		private InetAddress getIp() {
			InetAddress ip=null;
			try {
				Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
				while (interfaces.hasMoreElements()) {
					NetworkInterface ni = (NetworkInterface) interfaces.nextElement();
					Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
					while (inetAddresses.hasMoreElements()) {
						InetAddress inetAddress = inetAddresses.nextElement();
						if (!inetAddress.isLoopbackAddress()) {
							ip = inetAddress;
						}
					}
				}
			} catch (SocketException e) {
				log.error("::",e);
			}
			if(ip==null) {
				try {
					ip=InetAddress.getLocalHost();
				} catch (UnknownHostException e) {
					log.error("::",e);
				}
			}
			return ip;
		}
	}
	public void setTimeTaskDao(TimeTaskDao timeTaskDao) {
		this.timeTaskDao = timeTaskDao;
	}
}
